package com.stonejinyan.game2048;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;

public class GameView extends GridLayout {

	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public GameView(Context context) {
		super(context);
		init();
	}

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init() {

		setBackgroundColor(0xffbbada0);
		setColumnCount(4);
		setOnTouchListener(new View.OnTouchListener() {

			private float startx, starty, offsetx, offsety;

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					startx = event.getX();
					starty = event.getY();
					break;
				case MotionEvent.ACTION_UP:
					offsetx = event.getX() - startx;
					offsety = event.getY() - starty;
					if (Math.abs(offsetx) > Math.abs(offsety)) {
						if (offsetx > 5) {
							swipeRight();
						} else if (offsetx < -5) {
							swipeLeft();
						}
					} else {
						if (offsety > 5) {
							swipeDown();
						} else if (offsety < -5) {
							swipeUp();
						}
					}
					break;
				default:
					break;
				}
				return true;
			}
		});
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		super.onSizeChanged(w, h, oldw, oldh);
		int cardWidth = (Math.min(w, h) - 10) / 4;
		addCard(cardWidth, cardWidth);
		startGame();
	}

	public void startGame() {
		MainActivity.getMainActivity().clearScore();
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				cards[x][y].setNum(0);
			}
		}
		addRandomNum();
		addRandomNum();
	}

	private void addCard(int cardWidth, int cardHeight) {

		Card card;
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				card = new Card(getContext());
				card.setNum(0);
				addView(card, cardWidth, cardHeight);

				cards[x][y] = card;
			}
		}
	}

	public void addRandomNum() {
		emptyPoints.clear();
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				if (cards[x][y].getNum() <= 0) {
					emptyPoints.add(new Point(x, y));
				}
			}
		}
		Point point = emptyPoints.remove((int) (Math.random() * emptyPoints
				.size()));
		cards[point.x][point.y].setNum(Math.random() > 0.1 ? 2 : 4);
	}

	private Card[][] cards = new Card[4][4];
	private List<Point> emptyPoints = new ArrayList<Point>();

	private void swipeUp() {
		boolean merge = false;
		for (int x = 0; x < 4; x++) {
			for (int y = 0; y < 4; y++) {
				for (int y1 = y + 1; y1 < 4; y1++) {
					if (cards[x][y1].getNum() > 0) {
						if (cards[x][y].getNum() <= 0) {
							cards[x][y].setNum(cards[x][y1].getNum());
							cards[x][y1].setNum(0);
							y--;
							merge = true;
						} else if (cards[x][y1].equals(cards[x][y])) {
							cards[x][y].setNum(cards[x][y].getNum() * 2);
							cards[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(
									cards[x][y].getNum());
							merge = true;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeDown() {
		boolean merge = false;
		for (int x = 0; x < 4; x++) {
			for (int y = 3; y >= 0; y--) {
				for (int y1 = y - 1; y1 >= 0; y1--) {
					if (cards[x][y1].getNum() > 0) {
						if (cards[x][y].getNum() <= 0) {
							cards[x][y].setNum(cards[x][y1].getNum());
							cards[x][y1].setNum(0);
							y++;
							merge = true;
						} else if (cards[x][y1].equals(cards[x][y])) {
							cards[x][y].setNum(cards[x][y].getNum() * 2);
							cards[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(
									cards[x][y].getNum());
							merge = true;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeLeft() {
		boolean merge = false;
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				for (int x1 = x + 1; x1 < 4; x1++) {
					if (cards[x1][y].getNum() > 0) {
						if (cards[x][y].getNum() <= 0) {
							cards[x][y].setNum(cards[x1][y].getNum());
							cards[x1][y].setNum(0);
							x--;
							merge = true;
						} else if (cards[x1][y].equals(cards[x][y])) {
							cards[x][y].setNum(cards[x][y].getNum() * 2);
							cards[x1][y].setNum(0);
							MainActivity.getMainActivity().addScore(
									cards[x][y].getNum());
							merge = true;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}
	}

	private void swipeRight() {
		boolean merge = false;
		for (int y = 0; y < 4; y++) {
			for (int x = 3; x >= 0; x--) {
				for (int x1 = x - 1; x1 >= 0; x1--) {
					if (cards[x1][y].getNum() > 0) {
						if (cards[x][y].getNum() <= 0) {
							cards[x][y].setNum(cards[x1][y].getNum());
							cards[x1][y].setNum(0);
							x++;
							merge = true;
						} else if (cards[x1][y].equals(cards[x][y])) {
							cards[x][y].setNum(cards[x][y].getNum() * 2);
							cards[x1][y].setNum(0);
							MainActivity.getMainActivity().addScore(
									cards[x][y].getNum());
							merge = true;
						}
						break;
					}
				}
			}
			;
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}
	}

	private void checkComplete() {

		boolean complete = true;

		ALL: for (int y = 0; y < Config.LINES; y++) {
			for (int x = 0; x < Config.LINES; x++) {
				if (cards[x][y].getNum() == 0
						|| (x > 0 && cards[x][y].equals(cards[x - 1][y]))
						|| (x < Config.LINES - 1 && cards[x][y]
								.equals(cards[x + 1][y]))
						|| (y > 0 && cards[x][y].equals(cards[x][y - 1]))
						|| (y < Config.LINES - 1 && cards[x][y]
								.equals(cards[x][y + 1]))) {

					complete = false;
					break ALL;
				}
			}
		}

		if (complete) {
			AlertDialog alertDialog = new AlertDialog.Builder(getContext())
					.setTitle("指尖创维：stonejinyan")
					.setMessage("游戏结束")
					.setPositiveButton("重新开始",
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									startGame();
								}
							}).show();

		}

	}
}
